<?php

namespace app\service;

use app\model\BarrageModel;
use Exception;
use think\Collection;
use think\facade\Log;
use think\Paginator;
use Fukuball\Jieba\Jieba;
use Fukuball\Jieba\Finalseg;
use Fukuball\Jieba\JiebaAnalyse;
/**
 * @author wanQQ
 * @property string $error 错误信息
 */
class BarrageService extends BaseService
{
    public string $error = "";
    protected BarrageModel $barrageModel;
    protected function initialize() {
        $this->barrageModel = new BarrageModel();
    }

    /**
     * 存入弹幕
     * @param $info
     * @return bool
     */
    public function insertBarrage($info): bool
    {
        $data = [];
        $userIdLis = (new UserService())->getUserIdList();
        $num = count($info["content"]);
        $i = 0;
        foreach ($info["content"] as $value) {
            echo "弹幕解析ing " . $i++ . "/{$num} {$value['content']}",PHP_EOL;
            try {
                $result = $this->barrageModel
                    ->where([
                        ["room_id", "=", $info["fileInfo"]["room_id"]],
                        ["user_id", "=", $userIdLis[$value['id']]],
                        ["content", "=", $value['content']]
                    ])
                    ->count();
            }catch (Exception $e) {
                Log::error(date("Y-m-d H:i:s")."弹幕解析失败 ".json_encode($value,JSON_UNESCAPED_UNICODE)." 详情:" . $e->getMessage());
                exit();
            }
            if(!$result) {
                $data[] = [
                    "room_id" => $info["fileInfo"]["room_id"],
                    "file_date" => $info["fileInfo"]["file_date"],
                    "user_id" => $userIdLis[$value['id']],
                    "content" => $value['content'],
                    "create_time" => date("Y-m-d H:i:s"),
                    "update_time" => date("Y-m-d H:i:s")
                ];
            }
        }
        echo "弹幕解析ing 存入数据库",PHP_EOL;
        try {
            $result = $this->barrageModel->saveAll($data);
        } catch (Exception $e) {
            Log::error(date("Y-m-d H:i:s")."存入弹幕失败 详情:" . $e->getMessage());
            exit();
        }
        return (bool)$result;
    }

    /**
     * 获取指定房间号的指定时段内的弹幕数据（分页显示|全部显示）
     * @param array $roomID 房间号(数组)
     * @param string $startDate 开始日期
     * @param string $endDate 结束日期
     * @param int $pageSize 一页展示条数
     * @param int $model 模式 默认为分页模式
     * @param string $field 查询的字段
     * @return Collection|bool|array|Paginator
     */
    public function getBarrage(array $roomID,string $startDate,string $endDate,int $pageSize,int $model = 1,string $field = "*"): Collection|bool|array|Paginator
    {
        $dateRegular = "/^\d{4}(\/|-|\s|.)\d{1,2}(\/|-|\s|.)\d{1,2}$/";
        if(!(preg_match($dateRegular,$startDate) && preg_match($dateRegular,$endDate))) {
            $this->error = "开始日期或结束日期格式不正确";
            return false;
        }
        $request = [
            "room_id" => $roomID,
            "start_date" => $startDate,
            "end_date" => $endDate
        ];
        $data = [
            "room_id" => "in,room_id",
            "start_date" => ">,file_date",
            "end_date" => "<,file_date"
        ];
        $where = buildWhere($request,$data);
        try {
            if ($model === 1) {
                return $this->barrageModel->where($where)->field($field)->paginate($pageSize);
            }else {
                if("*" != $field && strstr($field,",")) {
                    return  $this->barrageModel->where($where)->field($field)->select();
                }else {
                    return $this->barrageModel->where($where)->column($field);
                }
            }
        }catch (Exception $e) {
            $this->error = "弹幕数据获取失败：" . $e->getMessage();
            Log::error(date("Y-m-d H:i:s")."弹幕数据获取失败 详情:" . $e->getMessage());
            exit();
        }
    }

    /**
     * 解析弹幕词频
     * @param array $roomID 房间号(数组)
     * @param string $startDate 开始日期
     * @param string $endDate 结束日期
     * @param int $top
     * @return array
     */
    public function parsingBarrage(array $roomID, string $startDate, string $endDate,int $top = 100): array
    {
        $content = $this->getBarrage($roomID,$startDate,$endDate,0,0,"content");
        ini_set('memory_limit', '1024M');
        Jieba::init();
        Finalseg::init();
        JiebaAnalyse::init();
        $tags = JiebaAnalyse::extractTags(implode("",$content), $top);
        $temp = [];
        $i = 0;
        foreach ($tags as $key => $value) {
            $temp[$i]["name"] = $key;
            $temp[$i++]["value"] = $value;
        }
        return $temp;
    }

    /**
     * 获取弹幕（发送者）排名
     * @param array $roomID 房间号(数组)
     * @param string $startDate 开始日期
     * @param string $endDate 结束日期
     * @param int $top
     * @return mixed
     */
    public function barrageSendTop(array $roomID, string $startDate, string $endDate,int $top = 10): mixed
    {
        $request = [
            "room_id" => $roomID,
            "start_date" => $startDate,
            "end_date" => $endDate
        ];
        $data = [
            "room_id" => "in,barrage.room_id",
            "start_date" => ">,file_date",
            "end_date" => "<,file_date"
        ];
        $where = buildWhere($request,$data);
        return $this->barrageModel
            ->join("bili_user","barrage.user_id = bili_user.id")
            ->where($where)
            ->field("user_name as name,COUNT(*) as value")
            ->group("user_id")
            ->order("value","desc")
            ->limit($top)
            ->select();
    }
}